﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;

using Whe;
using WOS;
using WOS.Common;

namespace WOS.Download
{
    [Flags]
    public enum DownloadEntryFlag
    {
        None = 0,
        Protected = 1,
        Suspected = 2,
    }

    public sealed class DownloadEntry : Entry, IStamped<DateTime>
    {
        #region Private Fields
        private readonly DateTime stamp;
        private readonly string destination;
        private readonly string origin;
        private readonly DataSize size;
        private readonly ProviderInfo[] providers;
        private readonly DownloadPriority priority;
        private readonly DownloadStatus status;
        private readonly Resource[] resources;
        private readonly DownloadEntryFlag flags;
        #endregion
        #region Constructors
        public DownloadEntry(Guid id, DateTime stamp, string name, int index, string destination, string origin, DataSize size, ProviderInfo[] providers, DownloadPriority priority, DownloadStatus status, Resource[] resources, DownloadEntryFlag flags, Func<Progress> progressFactory, Func<Speed> speedFactory, Func<Estimate> estimateFactory)
            : base(id, name, index, progressFactory, speedFactory, estimateFactory)
        {
            this.stamp = stamp;
            this.destination = destination;
            this.origin = origin;
            this.size = size;
            this.providers = providers;
            this.priority = priority;
            this.status = status;
            this.resources = resources;
            this.flags = flags;
        }
        #endregion

        #region Public Members
        public string Destination
        {
            get { return this.destination; }
        }

        public string Origin
        {
            get { return this.origin; }
        }

        public DataSize Size
        {
            get { return this.size; }
        }

        public ProviderInfo[] Providers
        {
            get { return this.providers; }
        }

        public DownloadPriority Priority
        {
            get { return this.priority; }
        }

        public DownloadStatus Status
        {
            get { return this.status; }
        }

        public Resource[] Resources
        {
            get { return this.resources; }
        }

        public override bool CanBeStarted()
        {
            return this.status == DownloadStatus.Stopped && this.resources.Any();
        }

        public override bool CanBeStopped()
        {
            return this.status == DownloadStatus.Queued || this.status == DownloadStatus.Downloading;
        }

        public override bool IsFinished()
        {
            return this.status == DownloadStatus.Finished;
        }

        public bool IsDownloading()
        {
            return this.status == DownloadStatus.Downloading;
        }

        public bool IsProtectedByPassword()
        {
            return (this.flags & DownloadEntryFlag.Protected) == DownloadEntryFlag.Protected;
        }

        public bool IsSuspectedBeingFake()
        {
            return (this.flags & DownloadEntryFlag.Suspected) == DownloadEntryFlag.Suspected;
        }
        #endregion

        #region IStamped<DateTime> Members
        public DateTime Stamp
        {
            get { return this.stamp; }
        }
        #endregion
    }

    public class DownloadEntryGroupEventArgs : EventArgs
    {
        #region Private Fields
        private readonly DownloadEntry[] targets;
        #endregion
        #region Constructors
        public DownloadEntryGroupEventArgs(params DownloadEntry[] targets)
        {
            this.targets = targets;
        }
        #endregion

        #region Public Members
        public DownloadEntry[] Targets
        {
            get { return this.targets; }
        }
        #endregion
    }

    public sealed class DownloadEntryProgressEventArgs : EntryEventArgs
    {
        #region Private Fields
        private readonly Progress progress;
        private readonly Speed speed;
        #endregion
        #region Constructors
        public DownloadEntryProgressEventArgs(DownloadEntry target, Progress progress, Speed speed)
            : base(target)
        {
            this.progress = progress;
            this.speed = speed;
        }
        #endregion

        #region Public Members
        public Progress Progress
        {
            get { return this.progress; }
        }

        public Speed Speed
        {
            get { return this.speed; }
        }
        #endregion
    }
}
